import java.util.PriorityQueue;

//模拟实现定时器

class MyTimerTask implements Comparable<MyTimerTask>{//这个类用来保存任务和时间
    private Runnable runnable;
    private long time;//这里的时间和delay不一样，这里的是到达某个时间点就开始执行任务，而后者是等过了多少分钟后

    public MyTimerTask(Runnable runnable,long time) {
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + time;//需要换算一下时间
    }
    public void run() {
        //用于执行任务
        runnable.run();
    }
    public long getTime() {
        return time;//返回时间。例如：14：00
    }

    @Override
    public int compareTo(MyTimerTask o) {
        return (int)(this.time - o.time);
    }
}

class MyTimer {
    private PriorityQueue<MyTimerTask> priorityQueue = new PriorityQueue<>();//保存任务
    private Object locker = new Object();

    public MyTimer() {//构造方法、一创建就开始等待执行线程
        Thread t = new Thread(()->{
           try {
               while (true) {//线程不断的执行
                   synchronized (locker) {//对 操作队列的操作进行加锁
                       if(priorityQueue.size() == 0) {
                           //continue;//暂时没有任务，进入下一轮循环
                           locker.wait();//没有任务时，阻塞等待
                       }
                       MyTimerTask task = priorityQueue.peek();//取出堆顶对象
                       long Time = task.getTime();//获取该任务需要执行的时间点，比如14：00
                       if(System.currentTimeMillis() >= Time) {//到达时间就执行
                           //比如现在的时间是14：20，就会进入if
                           task.run();//执行任务
                           priorityQueue.poll();
                       }else {
                           locker.wait(Time - System.currentTimeMillis());//等待指定的时间，否则死循环
                       }
                   }
               }
           }catch (InterruptedException e) {
               e.printStackTrace();
           }
        });
        t.start();
    }
    public void schedule (Runnable runnable,long time) {//用于添加任务
       synchronized (locker) {//对操作对象的进行加锁
           MyTimerTask task = new MyTimerTask(runnable,time);//每次的任务和时间就创建一个对象
           priorityQueue.offer(task);//将任务对象保存到优先级队列中
           locker.notify();//当有新任务进来时，就唤醒wait
       }
    }

}

public class Test4 {

    public static void main(String[] args) {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("2000ms之后执行的任务");
            }
        },2000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("1000ms之后执行的任务");
            }
        },1000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("3000ms之后执行的任务");
            }
        },3000);
    }
}
